﻿using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;

namespace BlogsAPI.Abstract
{
    using System;
    using Shorteners;

    /// <summary>
    /// Абстрактный класс, от которого наследуются все классы работающие с системами сокращения ссылок
    /// </summary>
    public abstract class Shortener : WebInterface
    {
        private readonly Regex rLink = new Regex(@"(https?://[^""']+)(?:\W|$)", Regexoptions);

        /// <summary>
        /// Версия API для тех, у кого она может меняться
        /// </summary>
        protected String _version = "v1";

        /// <summary>
        /// Имя пользователя для которого создан ключ
        /// </summary>
        protected String _username;

        /// <summary>
        /// Пароль пользователя для которого создан ключ
        /// </summary>
        protected String _password;

        /// <summary>
        /// Ключ приложения
        /// </summary>
        protected String _apikey;

        /// <summary>
        /// Переходить ли дальше
        /// </summary>
        protected virtual bool AllowAutoRedirect
        {
            get { return false; }
        }

        #region Main Functionality

        /// <summary>
        /// проверка, является ли передаваемый урл чатью этого сервиса
        /// </summary>
        public virtual Boolean ValidateLink(String sLink)
        {
            if(!String.IsNullOrEmpty(sLink))
            {
                //Берем параметр из свойс типа, если есть
                object[] attributes = GetType().GetCustomAttributes(typeof (SingleShortener), false);
                if (attributes.Length > 0)
                {
                    if (attributes.Any(attribute => sLink.ToLower().Contains(((SingleShortener)attribute).Link)))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// Преобразование одного типа данных в другой
        /// </summary>
        /// <param name="sInData">входные данные</param>
        /// <param name="sInType">входной тип</param>
        /// <param name="sOutType">выходной тип</param>
        /// <returns>Данные выходного типа</returns>
        public virtual String ConvertDataTo(String sInData,ItemType sInType,ItemType sOutType)
        {
            if(sInType != ItemType.ShortUrl) return null;//cant be!
            if(sOutType != ItemType.FullUrl) return null;//cant be!
            //
            string url = null;
            if(sInType == ItemType.ShortUrl && sOutType == ItemType.FullUrl)
            {
                url = sInData;
            }
            if (url == null) return null;
            try
            {
                //var resp = MakeRequest2(url, false);
                //if (resp.Headers.Location != null)
                //{
                //    return resp.Headers.Location.OriginalString;
                //}
                //string response = resp.Content.ReadAsStringAsync().Result;
                //Match m = rLink.Match(response);
                //if (m.Success)
                //{
                //    return m.Groups[1].Value;
                //}
                HttpWebRequest request = MakeRequest(url); //prepare web request
                request.Method = "GET";
                request.AllowAutoRedirect = AllowAutoRedirect;
                using (var resp = (HttpWebResponse)request.GetResponse())
                {
                    if (AllowAutoRedirect)
                    {
                        //мы уже дошли до последней страницы
                        return resp.ResponseUri.OriginalString;
                    }
                    if (!String.IsNullOrEmpty(resp.Headers[HttpResponseHeader.Location]) && rLink.Match(resp.Headers[HttpResponseHeader.Location]).Success)
                    {
                        return rLink.Match(resp.Headers[HttpResponseHeader.Location]).Groups[1].Value;
                    }
                    String response = (new StreamReader(resp.GetResponseStream())).ReadToEnd(); //fill up response
                    Match m = rLink.Match(response);
                    if (m.Success)
                    {
                        return m.Groups[1].Value;
                    }
                    resp.Close();
                }
            }catch(Exception e1)
            {
                Debug.WriteLine(e1.Message);
            }
            return null;
        }

        #endregion

    }
}
